package co.yixiang.business.post

import co.yixiang.annotation.AnonymousAccess
import co.yixiang.api.ApiResult
import co.yixiang.business.attention.AttentionService
import co.yixiang.business.comment.CommentService
import co.yixiang.entity.Comment
import co.yixiang.entity.LikeRepository
import co.yixiang.entity.Post
import co.yixiang.entity.Posts
import co.yixiang.util.Point2D
import co.yixiang.util.UserServiceKT
import co.yixiang.util.getApiResult
import co.yixiang.util.getDistance
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import me.liuwj.ktorm.database.Database
import me.liuwj.ktorm.dsl.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.dao.DuplicateKeyException
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController


interface PostService {

    /**
     * 插入或者更新帖子
     */
    fun insertOrUpdatePost(posts: Posts): ApiResult<*>

    /**
     * 移除帖子
     */
    fun removePost(id: Long): ApiResult<*>

    /**
     * 获取帖子列表
     */
    fun getPostList(postDto: PostDto): ApiResult<*>
}


@Service
@Transactional(rollbackFor = [Exception::class])
open class PostServiceImp(@Autowired var database: Database,
                          @Autowired var attentionService: AttentionService,
                          @Autowired var userServiceKT: UserServiceKT,
                          @Autowired var likeRepository: LikeRepository,
                          @Autowired var commentService: CommentService) : PostService {

    override fun insertOrUpdatePost(posts: Posts): ApiResult<*> {

        return try {
            database.insert(Post) {

                set(it.id, posts.id)
                set(it.content, posts.content)
                set(it.pics, posts.pics)
                set(it.createBy, posts.createBy)
                set(it.latitude, posts.latitude)
                set(it.longitude, posts.longitude)
                set(it.createTime, posts.createTime)
                set(it.deleted, posts.deleted)
            }
        }catch (e: DuplicateKeyException) {

            database.update(Post) {

                set(it.content, posts.content)
                set(it.pics, posts.pics)
                set(it.createBy, posts.createBy)
                set(it.latitude, posts.latitude)
                set(it.longitude, posts.longitude)
                set(it.createTime, posts.createTime)
                set(it.deleted, posts.deleted)

                where {
                    it.id eq  posts.id!!
                }
            }
        }.run { getApiResult(200, "操作成功") }
    }

    override fun removePost(id: Long): ApiResult<*> {

        return database.delete(Post) {it.id eq id}.run { getApiResult(200, "移除成功") }
    }

    override fun getPostList(postDto: PostDto): ApiResult<*> {

        return database.from(Post).select(Post.id, Post.content, Post.pics, Post.longitude, Post.latitude, Post.createTime, Post.createBy)
            .whereWithConditions { it ->

                when (postDto.type) {
                    1 -> {
                         attentionService.getMyAttentionList(postDto.userId!!).mapNotNull { it.userId }.run {
                             if (this.isEmpty()) it += Post.id eq 0
                             else it += Post.createBy inList (this)
                         }
                    }
                    2 -> {
                        TODO("同城")
                    }
                    3 -> {
                        it += Post.createBy eq postDto.userId!!
                    }
                }
            }.orderBy(Post.createTime.desc()).limit(postDto.pageNum!!- 1, postDto.pageSize!!)
            .map { row -> PostVo(
                userInfo = userServiceKT.getUserInfo(row[Post.createBy]!!),
                postId = row[Post.id],
                content = row[Post.content],
                pics = row[Post.pics]?.split(","),
                createTime = row[Post.createTime],
                longitude = row[Post.longitude],
                latitude = row[Post.latitude],
                distance = getDistance(Point2D(postDto.longitude?.toDouble(), postDto.latitude?.toDouble()),
                    Point2D(row[Post.longitude]?.toDouble(), row[Post.latitude]?.toDouble())).toString(),
                commentVos = commentService.getCommentVoListByPostId(row[Post.id]!!),
                commentCount = commentService.getCommentVoListByPostId(row[Post.id]!!)?.size,
                lastCommentTime = commentService.getCommentVoListByPostId(row[Post.id]!!).takeIf { it!!.isNotEmpty() }?.run { this[0].createTime },
                likeCount = likeRepository.getLikesByLikeId(row[Post.id]).toIterable().count()
            ) }.toList().run { getApiResult(200, "获取帖子数据成功") }
    }
}

@Api("帖子")
@RestController
@RequestMapping("/post")
class PostController(@Autowired val postService: PostService) {


    @ApiOperation("插入或者更新帖子")
    @PostMapping("/insertOrUpdatePost")
    @AnonymousAccess
    fun insertOrUpdatePost(posts: Posts): ApiResult<*> = postService.insertOrUpdatePost(posts)

    @ApiOperation("移除帖子")
    @PostMapping("/removePost")
    @AnonymousAccess
    fun removePost(id: Long): ApiResult<*> = postService.removePost(id)

    @ApiOperation("获取帖子列表")
    @PostMapping("/getPostList")
    @AnonymousAccess
    fun getPostList(postDto: PostDto): ApiResult<*> = postService.getPostList(postDto)

}
